package main

import (
	"fmt"
	"math"
	"time"
)

// 关于下载进度计算和显示的实用工具函数

// 计算网络速度
// size 一段时间内下载的数据大小，单位字节
// timeElapsed 经过的时间长度，单位毫秒
// 返回计算得到的网速，会自动换算单位
func computeSpeed(size int64, timeElapsed int) string {
	bytePerSecond := size / int64(timeElapsed) * 1000
	if 0 <= bytePerSecond && bytePerSecond <= 1024 {
		return fmt.Sprintf("%d Byte/s", bytePerSecond)
	}
	if bytePerSecond > 1024 && bytePerSecond <= int64(math.Pow(1024, 2)) {
		return fmt.Sprintf("%.2f KB/s", float64(bytePerSecond)/1024)
	}
	if bytePerSecond > 1024*1024 && bytePerSecond <= int64(math.Pow(1024, 3)) {
		return fmt.Sprintf("%.2f MB/s", float64(bytePerSecond)/math.Pow(1024, 2))
	}
	return fmt.Sprintf("%.2f GB/s", float64(bytePerSecond)/math.Pow(1024, 3))
}

// 在一个新的线程中，实时在控制台输出任务下载进度
//
// task 读取并显示进度的任务对象
func printProcess(task *ParallelGetTask) {
	go func() {
		// 上一次统计时的已下载大小，用于计算速度
		var lastDownloadSize int64 = 0
		for {
			// 如果全部任务完成则结束输出，并统计并发数
			allDone := true
			// 当前并发数
			currentTaskCount := 0
			for _, shardTask := range task.ShardTaskList {
				if !shardTask.TaskDone {
					allDone = false
					currentTaskCount += 1
				}
			}
			if allDone {
				break
			}
			// 统计所有分片已下载大小之和
			var totalDownloadSize int64 = 0
			for _, shardTask := range task.ShardTaskList {
				totalDownloadSize += shardTask.DownloadSize
			}
			// 计算速度
			currentDownload := totalDownloadSize - lastDownloadSize
			lastDownloadSize = totalDownloadSize
			speedString := computeSpeed(currentDownload, 300)
			// 输出到控制台
			// \r 回到行首
			// \033[2K 为ANSI转义控制字符，用于清空当前行
			fmt.Printf("\r\033[2K当前并发数：%d 速度：%s 总进度：%.2f%%", currentTaskCount, speedString, float32(totalDownloadSize)/float32(task.TotalSize)*100)
			// 等待300ms
			time.Sleep(300 * time.Millisecond)
		}
	}()
}